<?php
/**
 * Inter组件之Session存储器：Pdosqlite
 * 使用PDO连接SQLite 3
 * 部分代码思路来自cmstop{@link http://www.cmstop.com}，在此感谢！
 *
 * @author Horse Luke<horseluke@126.com>
 * @copyright Horse Luke, 2010
 * @license the Apache License, Version 2.0 (the "License"). {@link http://www.apache.org/licenses/LICENSE-2.0}
 * @version $Id: Pdosqlite.php 153 2011-02-04 09:48:39Z horseluke@126.com $
 * @package Inter_Session
 * @subpackage Inter_Session_Storage
 */
class Inter_Session_Storage_Pdosqlite extends Inter_Session_Storage_Abstract{
    
    /**
     * 配置选项数组
     * @var array
     */
    protected $_config = array();
    
    /**
     * PDO实例
     * @var PDO
     */
    protected $_PDO = null;

    /**
     * 是否已经连接？
     * @var bool
     */
    protected $_connected = false;
    
    /**
     * 是否已经运行了GC？
     * @var bool
     */
    protected $_gcRunned = false;
    
    /**
     * timestamp
     * @var integer
     */
    protected $_timestamp = 0;

    /**
     * 构造函数
     */
    public function __construct(){
        $this->_init();
    }
    
    /**
     * 打开一个session
     * @param string $save_path
     * @param string $session_name
     * @return bool
     */
    public function open($save_path, $session_name){
        $this->_connect();
        return true;
    }
    
    /**
     * 关闭一个session
     * php mannual的matt at openflows dot org (20-Sep-2006 08:02)提到
     * Debian和Ubuntu发行版不会调用gc，所以在这里最好手工以概率触发一下。
     * BUT IS THAT TRUE?
     * @return bool
     * 
     */
    public function close(){
        if(rand($this->_config['session.gc_probability'],$this->_config['session.gc_divisor']) <= $this->_config['session.gc_probability']){
            $this->gc($this->_config['session.gc_maxlifetime']);
        }
        //$this->_disconnect();
    }
    
    /**
     * 读取一个session
     * @param string $id session id
     * @return string  session数据。按原样传出字符串
     */
    public function read($id){
        if(false == $this->_connected){
            return '';
        }
        
        $sPDO = $this->_PDO->prepare("SELECT `data` FROM {$this->_config['TBL_NAME']} WHERE `id`= ? ");
        if ($sPDO->execute( array($id) )) {
            $r = $sPDO->fetch(PDO::FETCH_ASSOC);
            return (string)$r['data'];
        }else{
            return '';
        }
    }
    
    /**
     * 写入一个session
     * @param string $id session id
     * @param string $sess_data session数据。为兼容php自身行为，请保证传入的是字符串
     */
    public function write($id, $sess_data){
        if(false == $this->_connected){
            return false;
        }
        $sPDO = $this->_PDO->prepare( "REPLACE INTO {$this->_config['TBL_NAME']} (`id`, `lasttime`, `data`) VALUES(?, ?, ?)" );
        return $sPDO->execute( array($id, $this->_timestamp, $sess_data) );
    }
    
    /**
     * 销毁一个session
     * @param string $id session id
     */
    public function destroy($id){
        if(false == $this->_connected){
            return false;
        }
        $sPDO = $this->_PDO->prepare( "DELETE FROM {$this->_config['TBL_NAME']} WHERE `id` = ? " );
        return $sPDO->execute( array($id) );
    }
    
    /**
     * session回收
     * @param integer $maxlifetime session存活时间
     */
    public function gc($maxlifetime){
        if( true == $this->_gcRunned ){
            return true;
        }
        if(false == $this->_connected){
            return false;
        }
        $expiretime = intval($this->_timestamp - $maxlifetime);
        $this->_PDO->exec( "DELETE FROM {$this->_config['TBL_NAME']} WHERE `lasttime` < '{$expiretime}'" );
        $this->_gcRunned = true;
    }
    
    /**
     * 初始化本类相关资源
     */
    protected function _init(){
        $this->_readConfig();
        $this->_timestamp = time();
    }
    
    /**
     * 读取本类的配置文件，并且存放到$this->_config中
     */
    protected function _readConfig(){
        $this->_config = require dirname(__FILE__). '/../../../../Config/'. __CLASS__. '.php';
    }
    
    /**
     * 连接数据库
     */
    protected function _connect(){
        if(false == $this->_connected){
            $this->_PDO = new PDO("sqlite:{$this->_config['DB_PATH']}");
            $this->_PDO->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            $this->_checkTableExist();
            $this->_connected = true;
        }
    }
    
    /*
     * 断开数据库
     */
    /*
    protected function _disconnect(){
        if(true == $this->_connected){
            $this->_PDO = null;
            $this->_connected = false;
        }
    }
    */
    
    /**
     * 检查session表是否存在，不存在则建表
     */
    protected function _checkTableExist(){
        $sPDO = $this->_PDO->query("SELECT name FROM sqlite_master WHERE type='table' AND name='{$this->_config['TBL_NAME']}' LIMIT 0,1");
        $result = $sPDO->fetchAll(PDO::FETCH_ASSOC);
        if(empty($result)){
            $this->_createTable();
        }
    }
    
    /**
     * 建立session表
     */
    protected function _createTable(){
        $this->_PDO->exec(sprintf($this->_config['TBL_DDL'], $this->_config['TBL_NAME']));
        $this->_PDO->exec(sprintf($this->_config['TBL_INDEX_DDL'], $this->_config['TBL_NAME']));
    }
    
    
}